﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tea.Parser {

    #region Core

    /// <summary>
    /// 为所有节点提供抽象基类。
    /// </summary>
    public abstract class Node {

        /// <summary>
        /// 获取开始位置。
        /// </summary>
        public Location StartLocation {
            get;
            private set;
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        public abstract Location EndLocation {
            get;
        }

        /// <summary>
        /// 初始化 <see cref="Tea.Parser.Node"/> 的新实例。
        /// </summary>
        protected Node() {

        }

        protected Node(Location location) {
            StartLocation = location;
        }

        public virtual bool HasSideEffects {
            get {
                return false;
            }
        }

        ///// <summary>
        ///// 获取和设置用户数据。
        ///// </summary>
        //public object UserData {
        //    get;
        //    set;
        //}

        /// <summary>
        /// 接受子节点
        /// </summary>
        /// <param name="visitor"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        [System.Diagnostics.DebuggerStepThrough]
        public abstract void Accept(IAstVisitor visitor);

        /// <summary>
        /// 将当前节点写入指定的 CodeWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public abstract void Write(CodeWriter writer);

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString() {
            StringBuilder sb = new StringBuilder();
            CodeWriter writer = new CodeWriter(sb);
            Write(writer);
            return sb.ToString();
        }

        public string GenerateC() {
            StringBuilder sb = new StringBuilder();
            CodeWriter writer = new CodeWriter("\r\n", "\t", sb);
            GenerateC(writer);
            return sb.ToString();
        }

        public abstract void GenerateC(CodeWriter writer);
    }

    /// <summary>
    /// 内部使用的节点集合。
    /// </summary>
    /// <typeparam name="T">节点类型。</typeparam>
    public class NodeList<T> : List<T>
        where T : Node {

    }

    /// <summary>
    /// 表示一个表达式。
    /// </summary>
    public abstract class Expression : Node {

        protected Expression(Location location)
            : base(location) {

        }

        public virtual Type Type {
            get {
                return Type.Unknown;
            }
        }

        /// <summary>
        /// 将当前节点写入指定的 CodeWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(CodeWriter writer) {
            writer.Write(ToString());
        }

        public override void GenerateC(CodeWriter writer) {

        }
    }

    /// <summary>
    /// 表示一个语句。
    /// </summary>
    public abstract class Statement : Node {

        protected Statement() {

        }

        /// <summary>
        /// 初始化 <see cref="Tea.Parser.Statement"/> 的新实例。
        /// </summary>
        /// <param name="location">开始位置。</param>
        /// <param name="endLocation">结束位置。</param>
        protected Statement(Location location)
            : base(location) {

        }

        /// <summary>
        /// 获取当前是否为空语句。
        /// </summary>
        public virtual bool IsEmpty {
            get {
                return false;
            }
        }

        public bool NoSemicolon {
            get;
            set;
        }

        public override void Write(CodeWriter writer) {
            if (!NoSemicolon)
                writer.Write(';');
        }

        public override void GenerateC(CodeWriter writer) {
            
        }
    }

    #endregion

    #region Statement

    /// <summary>
    /// 表示一个表达式语句。
    /// </summary>
    public class ExpressionStatement : Statement {

        /// <summary>
        /// 获取表达式。
        /// </summary>
        public Expression Expression {
            get;
            private set;
        }

        public override Location EndLocation {
            get {
                return Expression.EndLocation;
            }
        }

        /// <summary>
        /// 初始化 <see cref="Tea.Parser.ExpressionStatement"/> 的新实例。
        /// </summary>
        /// <param name="expression">表达式。</param>
        /// <param name="location">开始位置。</param>
        /// <param name="endLocation">结束位置。</param>
        public ExpressionStatement(Expression expression)
            : base(expression.StartLocation) {
            Expression = expression;
        }


        public override void Write(CodeWriter writer) {
            Expression.Write(writer);

            base.Write(writer);
        }

        public override string ToString() {
            string value = Expression.ToString();
            return !NoSemicolon ? value + ';' : value;
        }

        [System.Diagnostics.DebuggerStepThrough]
        public override void Accept(IAstVisitor visitor) {
            visitor.VisitExpressionStatement(this);
        }

        public override void GenerateC(CodeWriter writer) {
            Expression.GenerateC(writer);
            writer.Write(';');
        }
    }

    /// <summary>
    /// 表示一个脚本块。 
    /// </summary>
    public class Block : BreakableStatement, IScopeNode {

        /// <summary>
        /// 当前的全部语句。
        /// </summary>
        NodeList<Statement> _statements = new NodeList<Statement>();

        /// <summary>
        /// 获取当前的全部语句。
        /// </summary>
        public NodeList<Statement> Statements {
            get {
                return _statements;
            }
        }

        // 由于 Block 是特殊的， Block 需要先创建，然后才能知道位置。

        /// <summary>
        /// 结束位置。
        /// </summary>
        internal Location endLocation;

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location EndLocation {
            get {
                return endLocation;
            }
        }

        public Block()
            : this(null, Location.Empty) {

        }

        public Block(LabelSet labels)
            : this(labels, Location.Empty) {

        }

        /// <summary>
        /// 初始化 <see cref="Tea.Parser.Block"/> 的新实例。
        /// </summary>
        /// <param name="breakTarget">中断后的目标语句。</param>
        /// <param name="label">标签。</param>
        /// <param name="location">开始位置。</param>
        /// <param name="endLocation">结束位置。</param>
        public Block(LabelSet labels, Location location)
            : base(labels, location) {

        }

        /// <summary>
        /// 返回当前语句是否简单。
        /// </summary>
        /// <returns>如果可以内联，返回 true 。</returns>
        public virtual bool IsInlineable {
            get {
                //        int count = statements_.length();
                //for (int i = 0; i < count; ++i) {
                //  if (!statements_[i]->IsInlineable()) return false;
                //}
                //return true;

                return true;
            }
        }

        /// <summary>
        /// 获取当前块是否为初始化的块 。
        /// </summary>
        public bool IsInitizlizerBlock {
            get;
            internal set;
        }

        Dictionary<string, TokenType> _maps;

        public void AddSymbol(string name, TokenType declType) {

            if (_maps == null)
                _maps = new Dictionary<string, TokenType>();


            _maps[name] = declType;

        }

        public TokenType GetSymbol(string name) {
            return _maps[name];
        }

        IScopeNode IScopeNode.GetDefinedBlock(string name) {
            return GetDefinedBlock(name);
        }

        /// <summary>
        /// 在当前块和父块搜索已经定义了变量名为 <paramref name="name"/> 的块。
        /// </summary>
        /// <param name="name">查找的名字。</param>
        /// <returns>返回找到块。如果找不到返回 null 。</returns>
        public Block GetDefinedBlock(string name) {
            for (BreakableStatement b = this; b != null; b = b.Parent) {
                Block target = b as Block;
                if (target != null && target._maps != null && target._maps.ContainsKey(name))
                    return target;
            }
            return null;
        }


        public override void Write(CodeWriter writer) {
            writer.Write('{');
            writer.Indent();

            foreach (Statement f in Statements) {
                writer.WriteLine();
                f.Write(writer);
            }

            writer.UnIndent();
            writer.Write('}');

        }

        public override void Accept(IAstVisitor visitor) {
            visitor.VisitBlock(this);
        }

        NodeList<FunctionDeclaration> _fns;

        public NodeList<FunctionDeclaration> Functions {
            get {

                if (_fns == null)
                    _fns = new NodeList<FunctionDeclaration>();
                return _fns;
            }
        }

        public void AddFunction(FunctionDeclaration fn) {
            AddSymbol(fn.Name, TokenType.Var);

            Functions.Add(fn);
        }

        public override void GenerateC(CodeWriter writer) {
            foreach (Statement s in Statements) {
                s.GenerateC(writer);
            }
        }
    }

    public class Module : Block {

        public override void Accept(IAstVisitor visitor) {
            visitor.VisitModule(this);
        }

    }

    /// <summary>
    /// 变量定义节点。
    /// </summary>
    public class VariableDeclaration : Node {

        public Identifier Name {
            get;
            private set;
        }

        public Expression Initialiser {
            get;
            private set;
        }

        public override Location EndLocation {
            get {
                return Initialiser == null ? Name.EndLocation : Initialiser.EndLocation;
            }
        }

        public VariableDeclaration(Identifier name, Expression initialiser)
            : base(name.StartLocation) {
            Name = name;
            Initialiser = initialiser;
        }

        public override void Write(CodeWriter writer) {
            Name.Write(writer);
            if (Initialiser != null) {
                writer.Write(" = ");
                Initialiser.GenerateC(writer);
            }
        }

        public override void Accept(IAstVisitor visitor) {
            visitor.VisitVariableDeclaration(this);
        }

        public override void GenerateC(CodeWriter writer) {
            Name.GenerateC(writer);

            if (Initialiser != null) {
                writer.Write(" = ");
                Initialiser.GenerateC(writer);
            }
        }
    }

    public class VariableStatement : Statement {

        public Type Type {
            get;
            set;
        }

        /// <summary>
        /// 获取当前 var 语句定义的所有变量。
        /// </summary>
        public NodeList<VariableDeclaration> Variables {
            get;
            private set;
        }

        /// <summary>
        /// 结束位置。
        /// </summary>
        Location _endLocation;

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location EndLocation {
            get {
                return _endLocation;
            }
        }

        public VariableStatement(NodeList<VariableDeclaration> s, Location startLocation, Location endLocation)
            : base(startLocation) {
            Variables = s;
            Type = Type.Unknown;
            _endLocation = endLocation;
        }

        protected virtual string DeclString {
            get {
                return "var";
            }
        }

        public override void Write(CodeWriter writer) {
            writer.Write(DeclString);

            bool hasComma = false;
            foreach (VariableDeclaration vd in Variables) {
                if (hasComma) {
                    writer.Write(',');
                } else {
                    hasComma = true;
                }


                writer.Write(' ');
                vd.Write(writer);
            }

            base.Write(writer);
        }

        [System.Diagnostics.DebuggerStepThrough]
        public override void Accept(IAstVisitor visitor) {
            visitor.VisitVariableStatement(this);
        }

        public override void GenerateC(CodeWriter writer) {
            writer.Write(Type.Name);
            writer.Write(' ');


            bool hasComma = false;
            foreach(VariableDeclaration vd in Variables){
                if (hasComma) {
                    writer.Write(',');
                    writer.Write(' ');
                } else {
                    hasComma = true;
                }

                vd.GenerateC(writer);
            }

            writer.Write(';');
        }
    }

    /// <summary>
    /// 表示 If 语句。
    /// </summary>
    public class IfStatement : Statement {

        /// <summary>
        /// 获取条件。
        /// </summary>
        public Expression Condition {
            get;
            private set;
        }

        /// <summary>
        /// 获取当前的则的部分。
        /// </summary>
        public Statement Then {
            get;
            private set;
        }

        /// <summary>
        /// 获取当前的否则的部分。
        /// </summary>
        public Statement Else {
            get;
            private set;
        }

        /// <summary>
        /// 结束位置。
        /// </summary>
        Location _endLocation;

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location EndLocation {
            get {
                return _endLocation;
            }
        }

        /// <summary>
        /// 初始化 <see cref="Tea.Parser.IfStatement"/> 的新实例。
        /// </summary>
        /// <param name="condition">条件。</param>
        /// <param name="thenStatmement">当前的则的部分。</param>
        /// <param name="elseStatmement">当前的否则的部分。</param>
        /// <param name="location">开始位置。</param>
        /// <param name="endLocation">结束位置。</param>
        public IfStatement(Expression condition, Statement thenStatmement, Statement elseStatmement, Location location, Location endLocation)
            : base(location) {
            Condition = condition;
            Then = thenStatmement;
            Else = elseStatmement;
            _endLocation = endLocation;
        }


        public override void Write(CodeWriter writer) {
            writer.WriteSingleLine("if (");
            Condition.Write(writer);
            writer.WriteLine(")");
            writer.Indent();
            Then.Write(writer);
            writer.UnIndent();
            writer.WriteIndent();

            if (!Else.IsEmpty) {
                writer.Write(" else ");
                writer.Indent();
                Else.Write(writer);
                writer.UnIndent();
            }

            base.Write(writer);
        }

        [System.Diagnostics.DebuggerStepThrough]
        public override void Accept(IAstVisitor visitor) {
            visitor.VisitIfStatement(this);
        }


        public override void GenerateC(CodeWriter writer) {
            writer.WriteSingleLine("if (");
            Condition.GenerateC(writer);
            writer.WriteLine(")");
            writer.Indent();
            Then.GenerateC(writer);
            writer.UnIndent();
            writer.WriteIndent();

            if (!Else.IsEmpty) {
                writer.Write(" else ");
                writer.Indent();
                Else.GenerateC(writer);
                writer.UnIndent();
            }

        }
    }

    #endregion

    #region Expression

    /// <summary>
    /// 标识符的常量。
    /// </summary>
    public class NullLiteral : Expression {

        public override Type Type {
            get {
                return Type.Null;
            }
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        public override Location EndLocation {
            get {
                return StartLocation + 4;
            }
        }

        /// <summary>
        /// 初始化 <see cref="Tea.Parser.StringLiteral"/>  的新实例。
        /// </summary>=
        /// <param name="location">开始位置。</param>=
        public NullLiteral(Location location)
            : base(location) {

        }

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString() {
            return "null";
        }

        [System.Diagnostics.DebuggerStepThrough]
        public override void Accept(IAstVisitor visitor) {
            visitor.VisitNullLiteral(this);
        }


        #region ILiteral 成员


        /// <summary>
        /// 获取当前文本真正的字符串值。
        /// </summary>
        /// <value></value>
        public string Value {
            get {
                return "null";
            }
        }

        #endregion

        public override void GenerateC(CodeWriter writer) {
            writer.Write("NULL");
        }
    }

    #endregion


}
